/*
 * Created by SharpDevelop.
 * User: MyWife
 * Date: 4/16/2011
 * Time: 3:01 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using popLib;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
using popLib.ExtensionClass;

namespace WebRemoteDesktop
{	
	/// <summary>
	/// Description of Form1.
	/// </summary>
	public partial class Form1 : Form
	{
		Timer timer;
		public Form1()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
						
			ServerList = FormLib.getAppSettingINI("Setting", "ServerList", "http://remote.mythtown.com");
			Server = FormLib.getAppSettingINI("Setting", "Server", "http://remote.mythtown.com");
			Interval = NumberLib.getInt(FormLib.getAppSettingINI("Setting", "Interval", "500"));
			FormLib.ApplyMinimumEffect(this,notifyIcon1);
			//FormLib.setTransparentForm(this,255,FormBackground.VistaBlueContainer, new TransparentFormOption());			
			timer = new Timer();
			timer.Tick += HandleCommandTimer;
						
		}
		
		#region Properties
		public int Interval{
			get{ return (int)numericUpDown1.Value; }
			set{ numericUpDown1.Value = value; }
		}
		
		public string Server{
			get{
				if( lbx_server.Items.Count == 0 ){
					lbx_server.Items.Add("http://remote.mythtown.com");
				}
				
				if(lbx_server.SelectedIndex == -1){
					lbx_server.SelectedIndex = 0;
				}
				
				return lbx_server.SelectedItem.ToString();
			}
			set{
				int indexer = lbx_server.FindStringExact(value);
				if( indexer == -1 ) lbx_server.Items.Add(value);								
				lbx_server.SelectedIndex = lbx_server.FindStringExact(value);
			}
		}
		
		public string ServerUpload{
			get{
				return (Server + "/upload.php").Replace("//upload.php","/upload.php");
			}
		}
		
		public string ServerCommand{
			get{
				return (Server + "/command.php").Replace("//command.php","/command.php");
			}
		}
		
		public string ServerList{
			get{
				string content = "";
				foreach( string server in lbx_server.Items ){
					content += server + ",";
				}
				content = content.EndsWith(",") ? (content+",").Replace(",,","") : content;
				return content;
			}
			set{
				lbx_server.Items.Clear();
				string[] items = value.Split(',');
				foreach( string item in items ){
					if( lbx_server.FindStringExact(item) == -1 )
						lbx_server.Items.Add(item);
				}
			}
		}
		#endregion
		
		#region Handle Functions
		void Form1FormClosing(object sender, FormClosingEventArgs e)
		{
			FormLib.setAppSettingINI("Setting", "Server", Server );
			FormLib.setAppSettingINI("Setting", "ServerList", ServerList );
			FormLib.setAppSettingINI("Setting", "Interval", Interval.ToString() );
		}
		
		void Btn_addurlClick(object sender, EventArgs e)
		{
			string url = "http://" + txt_url.Text.Trim().ToLower().Replace("http://","");
			
			if( StringLib.isValid(url) && lbx_server.FindStringExact(url) == -1 ){				
				lbx_server.Items.Add( url );
				txt_url.Clear();
			}			
		}
		
		void Btn_removeurlClick(object sender, EventArgs e)
		{
			if( lbx_server.SelectedIndex >= 0 ){
				lbx_server.Items.RemoveAt( lbx_server.SelectedIndex );
			}			
		}
		
		void btn_startClick(object sender, EventArgs e)
		{						
			if( btn_start.Text == "&Start" ){
				lbx_server.Enabled = false;
				timer.Interval = Interval;
				timer.Start();
				btn_start.Text = "&Stop";
			}else{
				timer.Stop();
				lbx_server.Enabled = true;
				btn_start.Text = "&Start";
			}
		}
		
		void HandleCommandTimer(object sender, EventArgs e){
			
			timer.Stop();			
						
			CommandHandler();
			
			timer.Start();
		}
		
		NetworkSecurity GetNetSec(){
			NetworkSecurity netsec = new NetworkSecurity();
			
			if( checkBox1.Checked ){
				netsec = new NetworkSecurity(host.Text, (int)port.Value, domain.Text, id.Text, pw.Text);
			}
			
			return netsec;
		}
		
		void CommandHandler(){
			
			
			
			ReturnSet result = NetLib.connectHttp(ServerCommand, new Hashtable(), GetNetSec());
			if( !result.Success ){
				//FileLib.WriteAppLog( result.Result );
				return;
			}
			string commandText = result.Result.ToString();
			if( commandText == "NO_COMMAND" ) return;
			string[] commands = StringLib.splitByAny( commandText, new string[]{"\r\n"} );
			
			int x, y;
			foreach(string command in commands){
				
				if( !StringLib.isValid(command) ) continue;
				
				string[] parts = StringLib.splitByAny( command, new string[]{"<&amp;>"} );
				x = NumberLib.getInt( parts[1] );
				y = NumberLib.getInt( parts[2] );
				
				switch(parts[0]){
					case "CLICK":
						WindowLib.MouseClick( MouseButtons.Left, x, y );
						break;
					case "DOUBLE_CLICK":
						WindowLib.MouseClick( MouseButtons.Left, x, y );
						WindowLib.MouseClick( MouseButtons.Left, x, y );
						break;
					case "RIGHT_CLICK":
						WindowLib.MouseClick( MouseButtons.Right, x, y );
						break;
					case "CENTER_CLICK":
						WindowLib.MouseClick( MouseButtons.Middle, x, y );
						break;
					case "CAPTURE":
						//do nothing because capture screen later
						break;
					case "MOVE":
						Cursor.Position = new Point(x,y);						
						break;
					case "DRAG_START":
						WindowLib.MouseClick( MouseButtons.Left, x, y, false );
						break;
					case "DRAG_STOP":
						WindowLib.MouseClick( MouseButtons.Left, x, y, true );
						break;
					case "TYPE":
						string content = parts[3].Replace("<&br;>","\r\n");
						WindowLib.MouseClick( MouseButtons.Left, x, y );
						ExecuteType(content);
						System.Threading.Thread.Sleep(100);
						break;
				}
			}
			
			System.Threading.Thread.Sleep(500);
			CaptureScreen();
		}
		
		void ExecuteType(string content){
			string[] lines = content.Split('\n');
			
			foreach( string line in lines ){
    			try{
					
					//if line start with .: -> paste line only
					if( line.StartsWith(".:") || line.StartsWith("..") || line.StartsWith("--") || line.StartsWith("::") ){
						ExecutePaste(line.Substring(2));
						continue;
					}
					
    				string[] keys = line.Replace("\r","").Split('+');
					
    				foreach( string key in keys ){
						if( key.Length != 1 ){
    						APILib.VK vkey = (APILib.VK)Enum.Parse( typeof(APILib.VK), key.ToUpper() );
							APILib.keybd_event ( (byte)vkey , 0, 0, 0);
						}else{
							APILib.keybd_event ( Convert.ToByte( Convert.ToInt16( key.ToUpper()[0] ) ) , 0, 0, 0);
						}
					}
					
					foreach( string key in keys ){
						if( key.Length != 1 ){
    						APILib.VK vkey = (APILib.VK)Enum.Parse( typeof(APILib.VK), key.ToUpper() );
							APILib.keybd_event ( (byte)vkey , 0, APILib.KEYEVENTF_KEYUP, 0);							
						}else{
							APILib.keybd_event ( Convert.ToByte( Convert.ToInt16(key.ToUpper()[0]) ) , 0, APILib.KEYEVENTF_KEYUP , 0);
						}
					}    
    			}catch{
					ExecutePaste(line);
				}
			}
		}
		
		void ExecutePaste(string content){
			//try{
				if( !StringLib.isValid(content) ) return;
				
				//copy to clipboard
				Clipboard.SetText( content );
				
				//Ctrl + V
				WindowLib.PressKeyGroup( new Keys[]{ Keys.Control, Keys.V } );
			//}catch{}
		}
		#endregion
		
		#region Screen handle functions
		Timer timer_capture;
		public void CaptureScreen(){
			if(timer_capture == null){
				timer_capture = new Timer();
				timer_capture.Interval = 100;
				timer_capture.Tick += TimerCaptureTick;
			}
			
			Clipboard.Clear();
			WindowLib.PressKey(Keys.PrintScreen);
			timer_capture.Start();
		}
		
		private void TimerCaptureTick(object sender, EventArgs e){
			if( Clipboard.ContainsImage() ){
				Image img = Clipboard.GetImage();
				Graphics gra = Graphics.FromImage(img);				
				gra.DrawImage( CommonResource.cursor , Cursor.Position );
				ValidateScreen(img);
				GC.Collect();
			}
			timer_capture.Stop();
		}
		
		int TotalPieces = 4;
		private void ValidateScreen(Image img){
			//spit the screen to many pieces
			int width  = img.Width / TotalPieces;
			int height  = img.Height / TotalPieces;			
						
			DateTime time = DateTime.Now;
			
			ArrayList pieceList = new ArrayList();
			string filename = "";
			
			ImageCodecInfo codecInfo = GetEncoderInfo(ImageFormat.Gif);
						
			EncoderParameters parameters = new EncoderParameters(1);
			parameters.Param[0] = new EncoderParameter(Encoder.Quality, 1L);
			
			for( int i = 0; i < TotalPieces ; i++ ){
				for( int j = 0; j < TotalPieces ; j++ ){
					//create new piece
					Image piece = new Bitmap( width, height );
					
					Graphics graphic = Graphics.FromImage(piece);
					graphic.DrawImageUnscaled(img, new Rectangle( -(j*width), -(i*height), piece.Width, piece.Height));
					
					
					filename = string.Format("{0}-{1}.gif",i,j);
					if( File.Exists(filename) ){
						Image old_piece = Image.FromFile( filename );
						if( ImageLib.CompareImagePixel( (Bitmap)piece, (Bitmap)old_piece ) != ImageLib.CompareResult.ciCompareOk ){
							old_piece.Dispose();
							piece.Save(filename, codecInfo, parameters);
							UploadScreen(filename, ServerUpload);
						}
					}else{
						piece.Save(filename, codecInfo, parameters);
						UploadScreen(filename, ServerUpload);
					}
					
					while( lockCounter > 3 )
						System.Threading.Thread.Sleep(100);
				}
			}
			
			timer_capture.Stop();											
		}
		
		public ImageCodecInfo GetEncoderInfo(ImageFormat format)
		{
			ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
			foreach( ImageCodecInfo codec in encoders ){
				if(codec.FormatID == format.Guid)
					return codec;
			}
			return encoders[0];
		}
		
		int lockCounter = 0;
		public void PerformUpload(object obj){
			string file = ((string[])obj)[0];
			string url = ((string[])obj)[1];			
			string indexer = Path.GetFileNameWithoutExtension(file);
			string randomName = Path.GetRandomFileName();
			
			Hashtable fileList = new Hashtable();
			fileList.Add( "file", file );
			
			Hashtable paramList = new Hashtable();
			paramList.Add( "ImageIndex", indexer );
			paramList.Add( "RandomName", randomName );
							
			int time = 0;
			ReturnSet result = null;
			
			while( time < 3 ){
				result = NetLib.UploadFileHttp( fileList, url, paramList, GetNetSec());
				
				if(result.Success){
					if(result.Result.ToString() == "OK")
						break;
					else FormLib.alert(result.Result + "\r\n" + result.Message);
				}
				
				time++;
			}
									
			lockCounter--;
		}
				
		private void UploadScreen( string file, string url ){
			lockCounter++;
			System.Threading.Thread temp = new System.Threading.Thread(PerformUpload);
			temp.IsBackground = true;
			temp.Start( new string[]{ file, url } );
			
//			PerformUpload(new string[]{ file, url });
		}
		#endregion
		
		void Button1Click(object sender, EventArgs e)
		{
			CaptureScreen();
		}
		
		void CheckBox1CheckedChanged(object sender, EventArgs e)
		{
			label6.Visible = label7.Visible = label8.Visible = label9.Visible = host.Visible = port.Visible = domain.Visible = id.Visible = pw.Visible = checkBox1.Checked;
			this.Height = checkBox1.Checked ? 345 : 235;
		}
	}
}
